package common

import (
	"fmt"
	"log"
	"net"
	"runtime"
	"syscall"
	"time"
)

// TCPOptimizer TCP连接优化器
// 实现BBR和CUBIC拥塞控制算法配置，提高网络传输稳定性和吞吐量
type TCPOptimizer struct {
	// 拥塞控制算法：bbr, cubic, reno
	CongestionControl string

	// TCP参数
	EnableKeepAlive   bool
	KeepAliveInterval time.Duration
	EnableNoDelay     bool // Nagle算法控制
	SendBuffer        int  // 发送缓冲区大小
	RecvBuffer        int  // 接收缓冲区大小

	// 统计信息
	OptimizedConnections int64
	FailedOptimizations  int64
}

// NewTCPOptimizer 创建TCP优化器
func NewTCPOptimizer() *TCPOptimizer {
	return &TCPOptimizer{
		CongestionControl: "bbr", // 默认使用BBR算法
		EnableKeepAlive:   true,
		KeepAliveInterval: 30 * time.Second,
		EnableNoDelay:     true,            // 禁用Nagle算法，降低延迟
		SendBuffer:        4 * 1024 * 1024, // 4MB发送缓冲区
		RecvBuffer:        4 * 1024 * 1024, // 4MB接收缓冲区
	}
}

// OptimizeConnection 优化TCP连接
// 应用BBR/CUBIC拥塞控制算法和其他TCP优化参数
func (o *TCPOptimizer) OptimizeConnection(conn net.Conn) error {
	tcpConn, ok := conn.(*net.TCPConn)
	if !ok {
		return fmt.Errorf("连接不是TCP连接")
	}

	var errors []error

	// 1. 设置TCP KeepAlive
	if o.EnableKeepAlive {
		if err := tcpConn.SetKeepAlive(true); err != nil {
			errors = append(errors, fmt.Errorf("设置KeepAlive失败: %v", err))
		} else {
			if err := tcpConn.SetKeepAlivePeriod(o.KeepAliveInterval); err != nil {
				errors = append(errors, fmt.Errorf("设置KeepAlive周期失败: %v", err))
			}
		}
	}

	// 2. 设置TCP NoDelay (禁用Nagle算法)
	if o.EnableNoDelay {
		if err := tcpConn.SetNoDelay(true); err != nil {
			errors = append(errors, fmt.Errorf("设置NoDelay失败: %v", err))
		}
	}

	// 3. 设置发送和接收缓冲区
	rawConn, err := tcpConn.SyscallConn()
	if err != nil {
		errors = append(errors, fmt.Errorf("获取syscall连接失败: %v", err))
	} else {
		err = rawConn.Control(func(fd uintptr) {
			// 设置发送缓冲区
			if o.SendBuffer > 0 {
				if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDBUF, o.SendBuffer); err != nil {
					errors = append(errors, fmt.Errorf("设置发送缓冲区失败: %v", err))
				}
			}

			// 设置接收缓冲区
			if o.RecvBuffer > 0 {
				if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVBUF, o.RecvBuffer); err != nil {
					errors = append(errors, fmt.Errorf("设置接收缓冲区失败: %v", err))
				}
			}

			// 4. 设置拥塞控制算法（仅Linux支持）
			if runtime.GOOS == "linux" {
				if err := o.setCongestionControl(int(fd)); err != nil {
					errors = append(errors, fmt.Errorf("设置拥塞控制算法失败: %v", err))
				}
			}
		})

		if err != nil {
			errors = append(errors, fmt.Errorf("Control调用失败: %v", err))
		}
	}

	// 记录结果
	if len(errors) > 0 {
		o.FailedOptimizations++
		log.Printf("⚠️ [TCP优化] 部分优化失败: %v", errors)
		// 即使部分失败，连接仍然可用
		return nil
	}

	o.OptimizedConnections++
	log.Printf("✅ [TCP优化] 连接优化成功: 拥塞控制=%s, NoDelay=%v, KeepAlive=%v",
		o.CongestionControl, o.EnableNoDelay, o.EnableKeepAlive)

	return nil
}

// setCongestionControl 设置TCP拥塞控制算法（Linux专用）
func (o *TCPOptimizer) setCongestionControl(fd int) error {
	if runtime.GOOS != "linux" {
		// 非Linux系统不支持，静默返回
		return nil
	}

	// TCP_CONGESTION 常量值为13
	const TCP_CONGESTION = 13

	// 尝试设置指定的拥塞控制算法
	err := syscall.SetsockoptString(fd, syscall.IPPROTO_TCP, TCP_CONGESTION, o.CongestionControl)
	if err != nil {
		// 如果设置失败（例如内核不支持BBR），尝试降级到CUBIC
		if o.CongestionControl == "bbr" {
			log.Printf("⚠️ [TCP优化] BBR不可用，降级到CUBIC")
			o.CongestionControl = "cubic"
			err = syscall.SetsockoptString(fd, syscall.IPPROTO_TCP, TCP_CONGESTION, "cubic")
			if err != nil {
				// 如果CUBIC也失败，使用系统默认（通常是reno或cubic）
				log.Printf("⚠️ [TCP优化] CUBIC不可用，使用系统默认拥塞控制算法")
				return nil // 不返回错误，使用系统默认
			}
		} else {
			return err
		}
	}

	return nil
}

// GetCongestionControl 获取当前拥塞控制算法（Linux专用）
// 注意：由于Go标准库没有提供GetsockoptString，这个函数返回配置的算法名称
func (o *TCPOptimizer) GetCongestionControl() string {
	return o.CongestionControl
}

// PrintStats 打印统计信息
func (o *TCPOptimizer) PrintStats() {
	log.Printf("📊 [TCP优化统计]")
	log.Printf("   ├─ 优化成功: %d 个连接", o.OptimizedConnections)
	log.Printf("   ├─ 优化失败: %d 个连接", o.FailedOptimizations)
	log.Printf("   ├─ 拥塞控制: %s", o.CongestionControl)
	log.Printf("   ├─ TCP NoDelay: %v", o.EnableNoDelay)
	log.Printf("   ├─ TCP KeepAlive: %v (%v)", o.EnableKeepAlive, o.KeepAliveInterval)
	log.Printf("   ├─ 发送缓冲区: %d bytes (%.2f MB)", o.SendBuffer, float64(o.SendBuffer)/(1024*1024))
	log.Printf("   └─ 接收缓冲区: %d bytes (%.2f MB)", o.RecvBuffer, float64(o.RecvBuffer)/(1024*1024))
}

// ApplicationLevelFlowControl 应用层流量控制
// 当操作系统不支持BBR/CUBIC时的备选方案
type ApplicationLevelFlowControl struct {
	// 滑动窗口大小
	WindowSize int

	// 当前窗口中的字节数
	CurrentBytes int

	// RTT (往返时间) 估算
	RTT time.Duration

	// 带宽估算 (bytes/second)
	EstimatedBandwidth int64

	// 慢启动阈值
	SlowStartThreshold int
}

// NewApplicationLevelFlowControl 创建应用层流量控制器
func NewApplicationLevelFlowControl() *ApplicationLevelFlowControl {
	return &ApplicationLevelFlowControl{
		WindowSize:         64 * 1024,             // 初始窗口64KB
		RTT:                50 * time.Millisecond, // 初始RTT估算50ms
		EstimatedBandwidth: 10 * 1024 * 1024,      // 初始带宽估算10MB/s
		SlowStartThreshold: 512 * 1024,            // 慢启动阈值512KB
	}
}

// AdjustWindow 根据网络状况调整窗口大小（简化的拥塞控制）
func (f *ApplicationLevelFlowControl) AdjustWindow(bytesAcked int, packetLoss bool) {
	if packetLoss {
		// 发生丢包，减小窗口（类似CUBIC的乘法减）
		f.WindowSize = f.WindowSize / 2
		f.SlowStartThreshold = f.WindowSize
		log.Printf("⚠️ [流量控制] 检测到丢包，窗口大小减半: %d bytes", f.WindowSize)
	} else {
		// 成功传输，增大窗口
		if f.WindowSize < f.SlowStartThreshold {
			// 慢启动阶段：指数增长
			f.WindowSize += bytesAcked
		} else {
			// 拥塞避免阶段：线性增长（类似CUBIC）
			f.WindowSize += (bytesAcked * bytesAcked) / f.WindowSize
		}

		// 限制最大窗口大小
		maxWindow := 4 * 1024 * 1024 // 4MB
		if f.WindowSize > maxWindow {
			f.WindowSize = maxWindow
		}
	}
}

// GetSendRate 获取当前发送速率限制（bytes/second）
func (f *ApplicationLevelFlowControl) GetSendRate() int64 {
	// 基于窗口大小和RTT计算发送速率
	// SendRate = WindowSize / RTT
	if f.RTT == 0 {
		return f.EstimatedBandwidth
	}

	rate := int64(float64(f.WindowSize) / f.RTT.Seconds())

	// 不超过估算带宽的120%
	maxRate := f.EstimatedBandwidth * 120 / 100
	if rate > maxRate {
		rate = maxRate
	}

	return rate
}

// UpdateRTT 更新RTT估算（使用指数加权移动平均）
func (f *ApplicationLevelFlowControl) UpdateRTT(newRTT time.Duration) {
	// EWMA: smoothed_rtt = 0.875 * smoothed_rtt + 0.125 * new_rtt
	f.RTT = time.Duration(float64(f.RTT)*0.875 + float64(newRTT)*0.125)
}

// UpdateBandwidth 更新带宽估算
func (f *ApplicationLevelFlowControl) UpdateBandwidth(bytesTransferred int64, duration time.Duration) {
	if duration == 0 {
		return
	}

	newBandwidth := bytesTransferred * int64(time.Second) / int64(duration)

	// EWMA平滑
	f.EstimatedBandwidth = (f.EstimatedBandwidth*7 + newBandwidth) / 8
}
